<?php

namespace 中文汇编器;

//包含工程文件
if ($argc == 1 or $argc > 2) 
    exit("使用方法：php 中文汇编器.php 工程名.prj.php");
else   
{
    require_once $argv[1];
	require_once '预处理.class.php';
	require_once '汇编.class.php';
}

mb_regex_encoding('UTF-8');
mb_internal_encoding("UTF-8");     

$局部标签 = [];
$全局标签 = [];

echo "预处理......\n";
if (!isset($输入文件, $段排序, $程序起始地址, $输出文件, $段基址))
    exit('错误：工程文件配置错误');

$chr2 = mb_substr($程序起始地址, 0, 2);
if ($chr2 == '0x' or $chr2 == '0b')
{
    $chrOther2 = mb_substr($程序起始地址, 2);
    if (is_numeric($chrOther2) == false)
        exit('错误：工程文件中【$程序起始地址】配置错误');
}

$chr1 = mb_substr($程序起始地址, 0, 1);
if ($chr1 == '0')
{
    $chrOther1 = mb_substr($程序起始地址, 1);
    if (is_numeric($chrOther1) == false)
        exit('错误：工程文件中【$程序起始地址】配置错误');
}

if (is_numeric($程序起始地址) == false)
    exit('错误：工程文件中【$程序起始地址】配置错误');

if ($段基址[0] != $程序起始地址)
    exit('错误：工程文件中【$程序起始地址】需要与【$段基址】第一项相同');

$第一遍扫描 = new 预处理($输入文件, $段排序, $程序起始地址, $段基址);
$全局标签 = $第一遍扫描->获取全局标签表();
$局部标签 = $第一遍扫描->获取局部标签表();
$中间代码 = $第一遍扫描->获取中间代码();
$段信息 = $第一遍扫描->获取段信息();

//print_r($全局标签);
//print_r($局部标签);
//print_r($中间代码);

echo "输出中间代码......" . $输出文件["中间代码"] . "\n";
$fmid = fopen($输出文件["中间代码"], "w");
$midCode = '';

for ($i = 0; $i < count($中间代码); $i++)
{
    if ($i != 0)
    {
        if ($中间代码[$i]["段基址"] == $中间代码[$i-1]["段基址"])
        {
            $sname = '';
            $j = $j + $中间代码[$i-1]["长度"];
            $listNum = dechex($j) . "\t";
        }
        else
        {
            $j = $中间代码[$i]["段基址"];
            $sname = $段信息[$中间代码[$i]["段序号"]]["标题"];
            $sname = "\n----------------------------《" . $sname . "》----------------------------\n";
            $listNum = dechex($j) . "\t";
        }
    }
    else
    {
        $j = $中间代码[$i]["段基址"];
        $sname = $段信息[$中间代码[$i]["段序号"]]["标题"];
        $sname = "\n----------------------------《" . $sname . "》----------------------------\n\n";
        $listNum = dechex($j) . "\t";
    }

    $m = count($全局标签);
    for ($a = 0; $a < $m; $a++)
    {
        $imm = $全局标签[$a]["段基址"] + $全局标签[$a]["偏移"];
        if ($imm == $j)
        {
            $lname = "【" . $全局标签[$a]["标签名"] . "】\n";
            goto NUMOP;
        }
        else
            $lname = '';
    }

    $m = count($局部标签);
    for ($b = 0; $b < $m; $b++)
    {
        $imm = $局部标签[$b]["段基址"] + $局部标签[$b]["偏移"];
        //var_dump($局部标签[$b]["标签名"], dechex($imm));
        if ($imm == $j)
        {
            $lname = "【" . $局部标签[$b]["标签名"] . "】\n";
            goto NUMOP;
        }
        else
            $lname = '';
    }

NUMOP:
    $midCode = $midCode . $sname . $lname . $listNum . $中间代码[$i]["内容"] . "\n";
}

fwrite($fmid, $midCode);
fclose($fmid);

//汇编();
echo "汇编......\n";
$第二遍扫描 = new 汇编($局部标签, $全局标签, $中间代码);
$finBinCode = $第二遍扫描->获取目标代码();

echo "输出目标文件......" . $输出文件["目标文件"] . "\n";
$fbin = fopen($输出文件["目标文件"], "w");
fwrite($fbin, $finBinCode);
fclose($fbin);

//print_r($段信息);
echo "输出地址文件......" . $输出文件["地址文件"] . "\n";
$fmap = fopen($输出文件["地址文件"], "w");
$mapStr = "{\"段数量\":\""  . count($段信息) . "\"}\n\n";
$secStr = '';
for ($i = 0; $i < count($段信息); $i++)
{
    if ($i == 0)
        $secAddr = 0;
    else
        $secAddr = $secAddr + $段信息[$i-1]["长度"];
    $secStr = $secStr . "{\n  \"" . $段信息[$i]["标题"] . "\": [\n    {\"目标设备入口地址\": \"0x" . dechex($段信息[$i]["基址"]) . "\"},\n    {\"目标文件位置\": \"0x" . dechex($secAddr) . "\"}\n  ]\n}\n\n";
}
$str = $mapStr . $secStr;
fwrite($fmap, $str);
fclose($fmap);

